package crack;

import fem2.AbstractStructuralStaticDemo;
import fem2.Constraint;
import fem2.Element;
import fem2.MaterialModel;
import fem2.Mesh;
import fem2.MeshPart;
import fem2.MeshUtilities;
import fem2.Model;
import fem2.NotImplementedError;
import fem2.analysis.Analysis;
import fem2.analysis.NonlinearStaticManualAnalysis;
import fem2.element.ConstantCrackElement;
import fem2.enu.EchoLevelType;
import fem2.enu.State;
import fem2.material.StVenantKirchhoffMM;
import fem2.observer.GidStressObserver;
import fem2.observer.TimeStepObserver;
import fem2.observer.TimingObserver;
import fem2.pre_and_post.GidPostStructural;
import fem2.strategies.Strategy;

public abstract class AbstractLshapeConstantCrack extends AbstractStructuralStaticDemo {

	public AbstractLshapeConstantCrack() {
		projectDir = "/home/hbui/kratos_janosch";
		projectName = "Lshape.gid";
	}

	@Override
	public Model createConditions(Model m) {
		Mesh mesh = m.getMesh();
		/*
		 * conditions
		 */
		Constraint c1 = new Constraint(false, false);
		Constraint c2 = new Constraint(true, false);
		double du = -0.01;
		c2.setValue(1, du);
		mesh.setConstraint(c1, MeshUtilities.seekNodesOnSurface(mesh, 0, 1, -1000));
		MeshUtilities.seekNode(mesh, 1000, 500).setConstraint(c2);
		return m;
	}

	@Override
	public MaterialModel createMaterial(Model m) {
		double E = 25850;
		double nu = 0.18;
		double t = 200;
		State ss = State.PLANE_STRESS;
		MaterialModel mm = new StVenantKirchhoffMM(E, nu, t, 0, ss);
		return mm;
	}

	@Override
	public Element createElement(MeshPart mp, MaterialModel mm) {
		double ft = 2.7;
		double Gf = 0.065;
		double H = -(ft * ft) / (2 * Gf);
		double km = 0.0;

		Element e = new ConstantCrackElement(mp, mm, H, km, ft);

		// e.setEchoLevel(EchoLevelType.OUTPUT, EchoLevelType.AUX3,
		// EchoLevelType.AUX4);
		e.setEchoLevel(EchoLevelType.OUTPUT);

		return e;
	}

	@Override
	public void run() {
		throw new NotImplementedError();
	}

	@Override
	public void run(int nt) {
		throw new NotImplementedError();
	}

	@Override
	public void run(double[] lambda) {
		Model m = createModel();

		Analysis an = new NonlinearStaticManualAnalysis(m, lambda);
		// m.setAssembler(new ParallelAssembler(m, 4));
		Strategy s = an.getStrategy();
		// s.setSolverType(SolverType.UMFPACK_SOLVER);
		s.setEchoLevel(EchoLevelType.OUTPUT, EchoLevelType.AUX1);
		an.getModel().setEchoLevel(EchoLevelType.AUX1);
		// s.setTolerance(1e-8);
		// s.setMaxNt(1000);

		if (meshFileName == null) {
			throw new Error("mesh file name was not set");
		}

		/*
		 * clean all previous post files
		 */
		String meshName = meshFileName.split("\\.")[0];

		GidPostStructural post = new GidPostStructural(projectDir, projectName, meshName);
		post.clearAllPostFiles();
		// post.clearAllPostFiles(meshName);

		TimeStepObserver tso = (TimeStepObserver) s.addObserver(new TimeStepObserver(s));

		GidStressObserver so = new GidStressObserver(m, tso, projectDir, projectName, meshName);

		// CrackObserver co = new CrackObserver(m, s);
		// co.setOutputTarget(projDir + '/' + projName + '/' + meshName +
		// "-with-crack.gmsh.msh");
		// co.setOutputTarget(projDir, projName, meshName);

		s.addObserver(so);
		// s.addObserver(co);
		s.addObserver(new TimingObserver());

		an.run();

		// post.moveAllPostFiles(meshName);

		/*
		 * post process
		 */
		// Mesh mesh = m.getMesh();
		// MeshUtilities meshUtil = new MeshUtilities(mesh);
		// String fn = projDir + '/' + projName + '/' + "mesh2.msh";
		// meshUtil.writeGmshMesh(mesh, fn);
		// Mesh mesh = m.getMesh();
		// for (int i = 0; i < mesh.countNodes(); i++) {
		// System.out.println(ArrayFormat.format(mesh.getNode(i).getUHatLocal()));
		// }

		// GidPostStructural post = new GidPostStructural(projDir, projName);
		// post.clearAllPostFiles();
		// post.writeMesh(m, 0);
		// post.writeNodalDisplacementResult(an, 0);
	}
}
